package br.com.requisicao.compra.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.hibernate.Session;

import br.com.requisicao.compra.dao.IGenericDAO;


public abstract class GenericDAO<T> implements IGenericDAO<T> {
	
	private Class<T> persistentClass;
	private Session session;
	private EntityManager em;
	private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("requisicao_compra");
	
	public GenericDAO(Session session) {
		this.session = session;
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	public Session getSession() {
		return this.session;
	}

	public T pesquisarPorId(Serializable id) {
		return (T) this.session.get(this.persistentClass, id);
	}
	
	public T salvar(T entidade) {
		return (T) this.session.merge(entidade);
	}

	public void excluir(T entidade) {
		this.session.delete(entidade);
	}
	
	public void beginTransaction() {
		em = emf.createEntityManager();

		em.getTransaction().begin();
	}

	protected T findOneResult(String namedQuery, Map<String, Object> parameters) {
		T result = null;

		try {
			Query query = em.createNamedQuery(namedQuery);

			// Method that will populate parameters if they are passed not null
			// and empty
			if (parameters != null && !parameters.isEmpty()) {
				populateQueryParameters(query, parameters);
			}

			result = (T) query.getSingleResult();

		} catch (NoResultException e) {
			System.out
					.println("No result found for named query: " + namedQuery);
		} catch (Exception e) {
			System.out.println("Error while running query: " + e.getMessage());
			e.printStackTrace();
		}

		return result;
	}

	private void populateQueryParameters(Query query,
			Map<String, Object> parameters) {
		for (Entry<String, Object> entry : parameters.entrySet()) {
			query.setParameter(entry.getKey(), entry.getValue());
		}
	}
}